package control.juego;

import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import juego.Juego;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import vista.VistaJuego;
import Estrategias.EstrategiaEstandarRushera;
import control.controladorJugadorMaquina.ControladorJugadorMaquina;
import excepcionesGenerales.ExcepImposibleEjecutar;

public class ControladorNuevoJuego {
	
	private VistaJuego vista;
	
	private static ControladorNuevoJuego Instance = null;
	
	/**
	 * Inicializa el controlador
	 * @param vista Vista del juego
	 */
	public ControladorNuevoJuego(){
		this.vista = VistaJuego.getInstance();
	}
	
	/**
	 * @return La instancia del controlador. 
	 * Si no existe la crea y la devuelve.
	 */
	public static ControladorNuevoJuego GetInstance(){
		if (Instance == null)
			return CrearInstancia();
		else
			return Instance;
	}
	
	/**
	 * Crea una nueva instancia del controlador
	 * @return la nueva instancia
	 */
	private static ControladorNuevoJuego CrearInstancia(){
		Instance = new ControladorNuevoJuego();
		return Instance;
	}
	/**
	 * Crea un nuevo juego
	 */
	public void crearNuevoJuego() {
		String ruta = obtenerRuta();
		vista.crearPantallaPrincipal();
		if(ruta != null){
			try{
			
			Document dom = obtenerDocumento(ruta);//abro el xml
			//Genero un nuevo juego, inicializo la vista y comienzo el primer turno
			Juego.getInstance().GenerarNuevoJuego(getStringRuta(dom,"ArchivoRegiones"),getStringRuta(dom,"ArchivoLimitrofes"),getStringRuta(dom,"ArchivoJugadores"));
			vista.StartGUI(getStringRuta(dom,"ArchivoVista"));
			ControladorSeleccion.GetInstance().limpiarSeleccion();
			Juego.getInstance().getRonda().addObserver(ControladorSeleccion.GetInstance());
			//agrego los jugadores de la maquina
			agregarJugadoresMaquina();
			Juego juego = Juego.getInstance(); 
			juego.cargarCondicionesIniciales();
			
			juego.getRonda().pasarTurno();
			} catch (ExcepImposibleEjecutar e1){
				JOptionPane.showMessageDialog(vista.getFrame(), "Error inicializando el juego");
				vista.crearPantallaPrincipal();
			}
		}
	}
	/**
	 *	Se encarga de agregar a la partida a los jugadores controlados
	 *	por la PC.
	 */
	private void agregarJugadoresMaquina() {
		int cantidadJugadores = -1;
		while (cantidadJugadores  < 0)
			cantidadJugadores = obtenerCantidadJugadores();
		for(int i = 0; i<cantidadJugadores;i++){
			ControladorJugadorMaquina jMaquina = new ControladorJugadorMaquina(new EstrategiaEstandarRushera()); 
			Juego.getInstance().AgregarJugador(jMaquina.getJugador());
			Juego.getInstance().getRonda().addObserver(jMaquina);
			
		}	
	}

	private int obtenerCantidadJugadores() {
		String cantDeMaq = JOptionPane.showInputDialog("Ingrese cantidad de PCs"); 
		int cant = -1;
		try{
			cant = Integer.parseInt(cantDeMaq);
		} catch (NumberFormatException e1){
			JOptionPane.showMessageDialog(VistaJuego.getInstance().getFrame(), "Valor mal ingresado","Error",JOptionPane.ERROR_MESSAGE);
			cant = -1;
		}
		return cant;
	}

	/**
	 * Devuelve el elemento de un xml con la forma <nombreElemento>####</nombreElemento>
	 * @param dom Documento de Dom parser de donde se obtiene el valor
	 * @param nombreElemento String que representa al nombre del elemento
	 * @return Un string con el elemento que se busco
	 */
	private String getStringRuta(Document dom, String nombreElemento){
		NodeList nodo = dom.getElementsByTagName(nombreElemento);
		Element el = (Element)nodo.item(0);
		String s = el.getTextContent(); 
		return s;
	}
	/**
	 * Genera un documento de Dom a partir de la ruta dada
	 * @param ruta Ruta del archivo xml
	 * @return Un document si lo logro abrir, caso contrario null
	 */
	private Document obtenerDocumento(String ruta){

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		Document dom = null;
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			dom = db.parse(ruta);
		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			ioe.printStackTrace();
		}
		return dom;
	}
	/**
	 * Abre una ventana de dialogo y permite seleccionar un archivo
	 * @return La ruta del archivo seleccionado
	 */
	private String obtenerRuta(){
		JFileChooser ventanaArchivos = new JFileChooser();
		//ventanaArchivos.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		ventanaArchivos.setFileFilter(new FiltroArchivos());
		ventanaArchivos.setAcceptAllFileFilterUsed(false);
		//ventanaArchivos.setAcceptAllFileFilterUsed(false);
		int opcion = ventanaArchivos.showOpenDialog(null);
		if(opcion == JFileChooser.APPROVE_OPTION){
			return ventanaArchivos.getSelectedFile().getPath();
		}
		else
			return null;
	}
	private class FiltroArchivos extends FileFilter{
		public boolean accept(File arg0) {
			
			if(arg0.isDirectory() || !arg0.exists() || arg0.getName().equals("config.xml"))
				return true;
			else
				return false;
		}
		public String getDescription() {
			return "Archivo inicio juego (Config.xml)";
		}
	}
	
}
